package com.util.concurrent.atomic;

import org.junit.Test;

import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 无锁boolean值，线程安全的
 */
public class AtomicBooleanDemo {

    private static boolean t = false;

    private static final AtomicBoolean atomic = new AtomicBoolean(false);

    /**
     * atomicBoolean 使用场景
     */
    @Test
    public void test01() {
        //当直接使用 t 做多线程的信号量时，非线程安全
        Runnable run = () -> {
            if (!t) {
                sleep(1000);//这里放大线程安全。因为判断和修改t非原子操作导致的线程安全问题
                t = true;//修改信号量，不让别的线程进来。
                System.out.println(Thread.currentThread().getName()+"开始执行时间为："+ LocalDateTime.now());
                //do something...
                t = false;
            }
        };
        //发现两个线程的开始执行时间没有相差一秒，表示该信号量没有将两个线程同步。
        new Thread(run,"t1").start();
        new Thread(run,"t2").start();

        sleep(3000);
        System.out.println("----------------------");

        //使用atomicboolean做信号量
        Runnable run2 = new Runnable() {
            @Override
            public void run() {
                if (atomic.compareAndSet(false,true)) {
                    sleep(1000);
                    System.out.println(Thread.currentThread().getName()+"开始执行时间为："+ LocalDateTime.now());
                    //do something...
                    atomic.set(false);
                }else{
                    sleep(500);//当他没有获取锁时，自选一会等等再重新获取锁
                    run();
                }
            }
        };

        //发现两个线程执行时间相差一秒，表示产生了异步
        new Thread(run2,"t3").start();
        new Thread(run2,"t4").start();


        sleep(10000);
    }

    private void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
